﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using Lou.Client.Service.Authentication;
using LoU.Client.DataContract;

namespace LoU.Client.Service
{
    public class WorldConnector
    {
        private static Dictionary<string, ChannelFactory<IService>> _factories = new Dictionary<string, ChannelFactory<IService>>();
        private static WebHttpBinding _binding;
        static WorldConnector()
        {
            _binding = new WebHttpBinding();
        }

        private IService GetChannel()
        {
            return _factories[this._world.BaseServiceUrl].CreateChannel();
        }
        protected TResult Call<TRequest, TResult>(Func<TRequest, TResult> method, TRequest request)
        {
            try
            {
                return method.Invoke(request);
            }
            finally
            {
                ICommunicationObject o = method.Target as ICommunicationObject;
                if (o != null)
                {
                    if (o.State == CommunicationState.Opened)
                    {
                        o.Close();
                    }
                    else
                    {
                        o.Abort();
                    }
                }
            }
        }
        private World _world;
        public WorldConnector(World world)
        {
            this._world = world;
            if (!_factories.ContainsKey(this._world.BaseServiceUrl))
            {
                ChannelFactory<IService> factory = new ChannelFactory<IService>(_binding, new EndpointAddress(this._world.BaseServiceUrl));
                factory.Endpoint.Behaviors.Add(new WebHttpBehavior
                {
                    DefaultOutgoingResponseFormat = WebMessageFormat.Json,
                    DefaultOutgoingRequestFormat = WebMessageFormat.Json,
                    DefaultBodyStyle = WebMessageBodyStyle.Bare,
                });
                _factories.Add(this._world.BaseServiceUrl, factory);
            }

            // Open session into world
            this.OpenSession();
        }
        private Guid _sessionId;
        private void OpenSession()
        {
            this._sessionId = this.Call(this.GetChannel().OpenSession, new OpenSessionRequest { SessionId = this._world.WorldId, Reset = false }).SessionId;
        }

        public GetServerInfoResponse GetServerInfo()
        {
            return this.Call(this.GetChannel().GetServerInfo, new BaseRequest { SessionId = this._sessionId });
        }

        public GetPlayerInfoResponse GetPlayerInfo()
        {
            return this.Call(this.GetChannel().GetPlayerInfo, new BaseRequest { SessionId = this._sessionId });
        }

        public int UpdateDiamonds()
        {
            return this.Call(this.GetChannel().UpdateDiamonds, new UpdateDiamondsRequest { SessionId = this._sessionId, Force = true });
        }

        public GetResoOptionsResponse GetResoOptions()
        {
            return this.Call(this.GetChannel().GetResoOptions, new BaseRequest { SessionId = this._sessionId });
        }

        public Distance[] GetDistance(int target)
        {
            return this.Call(this.GetChannel().GetDistance, new GetDistanceRequest { SessionId = this._sessionId, Target = target });
        }

        public GetReportResponse GetReport(int reportId)
        {
            return this.Call(this.GetChannel().GetReport, new GetReportRequest { SessionId = this._sessionId, ReportId = reportId });
        }

        public int ReportGetcount(int folder, int city, int mask)
        {
            return this.Call(this.GetChannel().ReportGetCount, new ReportGetCountRequest { SessionId = this._sessionId, City = city, Folder = folder, Mask = mask });
        }

        public ReportHeader[] ReportGetHeader(int folder, int city, int mask, int start, int end, int sort, bool ascending)
        {
            return this.Call(this.GetChannel().ReportGetHeader, new ReportGetHeaderRequest { SessionId = this._sessionId, City = city, Acsending = ascending, End = end, Folder = folder, Mask = mask, sort = sort, Start = start });
        }
    }
}
